﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows;

namespace SPNetworkTopology.ExternalWindows.ViewModel
{
    class DataLinkingViewModel : INotifyPropertyChanged
    {

        DataLinking _dataLinking;
        DataLinkingViewModelBase _currentPage;
        ReadOnlyCollection<DataLinkingViewModelBase> _pages;

        RelayCommand _moveNextCommand;
        RelayCommand _movePreviousCommand;
        RelayCommand _cancelCommand;

        bool isBackGroundOperationInProgress = false;

        public DataLinkingViewModel()
        {
            this._dataLinking = new DataLinking();
            this.CurrentPage = this.Pages[0];
        }

        #region Commands

        #region CancelCommand

        /// <summary>
        /// Returns the command which, when executed, cancels the order 
        /// and causes the Wizard to be removed from the user interface.
        /// </summary>
        public ICommand CancelCommand
        {
            get
            {
                if (_cancelCommand == null)
                    _cancelCommand = new RelayCommand(() => this.CancelOrder());

                return _cancelCommand;
            }
        }

        void CancelOrder()
        {
            _dataLinking = null;
            this.OnCancelRequestClose();
        }

        #endregion // CancelCommand

        #region MovePreviousCommand

        /// <summary>
        /// Returns the command which, when executed, causes the CurrentPage 
        /// property to reference the previous page in the workflow.
        /// </summary>
        public ICommand MovePreviousCommand
        {
            get
            {
                if (_movePreviousCommand == null)
                    _movePreviousCommand = new RelayCommand(
                        () => this.MoveToPreviousPage(),
                        () => this.CanMoveToPreviousPage);

                return _movePreviousCommand;
            }
        }

        bool CanMoveToPreviousPage
        {
            get { return 0 < this.CurrentPageIndex; }
        }

        void MoveToPreviousPage()
        {
            if (this.CanMoveToPreviousPage)
                this.CurrentPage = this.Pages[this.CurrentPageIndex - 1];
        }

        #endregion // MovePreviousCommand

        #region MoveNextCommand

        /// <summary>
        /// Returns the command which, when executed, causes the CurrentPage 
        /// property to reference the next page in the workflow.  If the user
        /// is viewing the last page in the workflow, this causes the Wizard
        /// to finish and be removed from the user interface.
        /// </summary>
        public ICommand MoveNextCommand
        {
            get
            {
                if (_moveNextCommand == null)
                    _moveNextCommand = new RelayCommand(
                        () => this.MoveToNextPage(),
                        () => this.CanMoveToNextPage);

                return _moveNextCommand;
            }
        }

        bool CanMoveToNextPage
        {
            get { return this.CurrentPage != null && this.CurrentPage.IsValid() && !this.isBackGroundOperationInProgress; }
        }

        void MoveToNextPage()
        {
            if (this.CanMoveToNextPage)
            {
                if(this.CurrentPage.GetType().Name.Equals("SPListInputViewModel"))
                {
                    SPListInputViewModel listViewModel = (SPListInputViewModel)this.CurrentPage;

                    listViewModel.worker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

                    if (!listViewModel.worker.IsBusy)
                    {
                        listViewModel.worker.RunWorkerAsync();
                    }

                    this.isBackGroundOperationInProgress = true;
                }

                else if (this.CurrentPageIndex < this.Pages.Count - 1)
                {
                    this.CurrentPage = this.Pages[this.CurrentPageIndex + 1];
                }
                else
                    this.OnFinishClick();
            }
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            SPListInputViewModel listViewModel = (SPListInputViewModel)e.Result;
            listViewModel.IsProgressbarVisible = Visibility.Collapsed;
            CommandManager.InvalidateRequerySuggested();

            if (listViewModel.HasNoError && this.CurrentPageIndex < this.Pages.Count - 1)
            {
                this.CurrentPage = this.Pages[2];
            }

            isBackGroundOperationInProgress = false;
        }

        #endregion // MoveNextCommand

        #endregion // Commands

        /// <summary>
        /// Returns a read-only collection of all page ViewModels.
        /// </summary>
        public ReadOnlyCollection<DataLinkingViewModelBase> Pages
        {
            get
            {
                if (_pages == null)
                    this.CreatePages();

                return _pages;
            }
        }

        /// <summary>
        /// Returns the page ViewModel that the user is currently viewing.
        /// </summary>
        public DataLinkingViewModelBase CurrentPage
        {
            get { return _currentPage; }
            private set
            {
                if (value == _currentPage)
                    return;

                if (_currentPage != null)
                    _currentPage.IsCurrentPage = false;

                _currentPage = value;

                if (_currentPage != null)
                    _currentPage.IsCurrentPage = true;

                this.OnPropertyChanged("CurrentPage");
                this.OnPropertyChanged("IsOnLastPage");
            }
        }

        /// <summary>
        /// Returns true if the user is currently viewing the last page 
        /// in the workflow.  This property is used by CoffeeWizardView
        /// to switch the Next button's text to "Finish" when the user
        /// has reached the final page.
        /// </summary>
        public bool IsOnLastPage
        {
            get { return this.CurrentPageIndex == this.Pages.Count - 1; }
        }


        int CurrentPageIndex
        {
            get
            {
                if (this.CurrentPage == null)
                {
                    Debug.Fail("Why is the current page null?");
                    return -1;
                }

                return this.Pages.IndexOf(this.CurrentPage);
            }
        }

        private void CreatePages()
        {
            var pages = new List<DataLinkingViewModelBase>();

            pages.Add(new WelcomePageViewModel());
            pages.Add(new SPListInputViewModel(this._dataLinking));
            pages.Add(new SPColumnSelectionViewModel(this._dataLinking));
            pages.Add(new SPListSummaryViewModel(this._dataLinking));

            _pages = new ReadOnlyCollection<DataLinkingViewModelBase>(pages);
        }

        /// <summary>
        /// Raise this event on button cancel click
        /// </summary>
        private void OnCancelRequestClose()
        {
            EventHandler handler = this.RequestClose;
            if (handler != null)
                handler(this, EventArgs.Empty);

            var currentPage = this.IsOnLastPage;
        }

        /// <summary>
        /// Raise the event on finish button click
        /// </summary>
        private void OnFinishClick()
        {
            EventHandler handler = this.RequestClose;
            if (handler != null)
                handler(this, EventArgs.Empty);

            //Create the recorset
            CreateRecordset recordSetCreation = new CreateRecordset(this.CurrentPage.DataLinking); 

            var currentPage = this.IsOnLastPage;
        }

        #region Events

        /// <summary>
        /// Raised when the wizard should be removed from the UI.
        /// </summary>
        public event EventHandler RequestClose;

        #endregion // Events

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}
